package com.tmt.im.service.interfaces.impl;

import com.alibaba.fastjson2.JSONObject;
import com.tmt.im.common.enums.ChatSessionType;
import com.tmt.im.common.pojo.ChatSessionMemberPoJo;
import com.tmt.im.common.pojo.ChatSessionPoJo;
import com.tmt.im.common.pojo.IMUserPoJo;
import com.tmt.im.service.config.beans.CurrentServiceProperties;
import com.tmt.im.service.controller.vo.*;
import com.tmt.im.service.helper.OperationFailInfoHelper;
import com.tmt.im.service.interfaces.ISessionMemberManager;
import com.tmt.im.service.interfaces.IYunXinInterface;
import com.tmt.im.service.mapstruct.ChatSessionPoJoMapStruct;
import com.tmt.im.service.service.ChatSessionService;
import com.tmt.im.service.service.SessionMemberService;
import com.tmt.springboot.common.restful.ExecuteResult;
import com.tmt.springboot.common.restful.IExecuteResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.security.Principal;
import java.text.MessageFormat;
import java.util.*;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/8/30 15:43
 * @Version 1.0
 **/
@Slf4j
@Order(1)
public class YunXinSessionMemberManager_V10 implements ISessionMemberManager, ApplicationContextAware {

    private ChatSessionService sessionService;

    private SessionMemberService sessionMemberService;

    private IYunXinInterface iYunXinInterface;

    private ChatSessionPoJoMapStruct sessionPoJoMapStruct;

    private CurrentServiceProperties serviceProperties;

    public List<ChatSessionDetailVo> getAllSession(Long creatorId, StringBuilder error) {
        //先到云信平台中创建群组。
        JSONObject jsonObject = iYunXinInterface.getAllInSession(creatorId, error);
        if (jsonObject == null) {
            return null;
        }

        //需要解散的群组ID与群主ID映射。
        Map<Long, Long> needDeletedSessionMap = new HashMap<>();
        IExecuteResult<List<ChatSessionPoJo>> result = sessionService.getAllInSession(creatorId, jsonObject, needDeletedSessionMap);
        if (result.getCode() != ExecuteResult.SUCCESS_CODE) {
            error.append(result.getMsg());
            return null;
        }

        //如果云信平台中存在的群组但本地表中没有该群组，则删除之。
        if (!CollectionUtils.isEmpty(needDeletedSessionMap)) {
            for (Long sessionId : needDeletedSessionMap.keySet()) {
                Long ownerId = needDeletedSessionMap.get(sessionId);
                if (iYunXinInterface.deleteSession(ownerId, ChatSessionType.GROUP, sessionId, error)) {
                    log.info("成功删除本地不存在的云信聊天群组(ID={})", sessionId);
                } else {
                    log.info("删除本地不存在的云信聊天群组(ID={})失败: {}", sessionId, error.toString());
                }
            }
        }

        return convertTo(result.getData());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public JoinSessionResponse joinSession(Long currentUserId, JoinSessionRequest request, Principal principal, StringBuilder error) {
        ChatSessionPoJo poJo = sessionService.findById(request.getTid());
        if (poJo == null) {
            error.append(MessageFormat.format("群组(ID={0})不存在", "" + request.getTid()));
            return null;
        }
        ChatSessionType type = Arrays.stream(ChatSessionType.values())
                .filter(x -> x.name().equals(poJo.getType())).findFirst().orElse(null);
        assert type != null;

        if (poJo.getJoinMode() == 2) {
            error.append("不允许任何人入群");
            return null;
        }

        //获取群的邀请配置参数.
        if (poJo.getInviteMode() == 0) {
            boolean isOwner = sessionService.isSessionOwner(currentUserId, poJo);
            boolean isManager = sessionService.isManager(currentUserId, poJo.getId());
            if (!isOwner && !isManager) {
                error.append("只有群主和管理员才能邀请其他人入群");
                return null;
            }
        }

        //不需要被邀请人同意直接将人拉入群中(可能需要审核)。
        JSONObject jsonObject = iYunXinInterface.joinSession(currentUserId, poJo.getId(), type, poJo.getBeInvitedMode(),
                request.getInviteMsg(), request.getMemberIds(), error);
        if (jsonObject == null) {
            return null;
        }

        List<OperationFailInfo> failInfos = OperationFailInfoHelper.convertTo(jsonObject);

        //创建用户入群记录(待审核或待同意).
        IExecuteResult<JoinSessionResponse> response = sessionMemberService.joinSession(currentUserId, request, principal, failInfos);
        if (response.getCode() != ExecuteResult.SUCCESS_CODE) {
            error.append(response.getMsg());
            return null;
        }
        return response.getData();
    }

    @Override
    public WaitingCheckInvitationResponse listInvitation(Long currentUserId, Long tid, int pageIndex, int pageSize, Principal principal, StringBuilder error) {
        return null;
    }

    @Override
    public boolean reviewInvitation(Long currentUserId, JoiningSessionReply reply, Principal principal, StringBuilder error) {
        return false;
    }

    /**
     * 被邀请人同意或不同意入群
     *
     * @param currentUserId
     * @param reply
     * @param principal
     * @param error
     * @return
     */
    @Override
    public boolean replyInvitation(Long currentUserId, JoiningSessionReply reply, Principal principal, StringBuilder error) {
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public KickOutSessionResponse kickOutSession(Long currentUserId, KickOutSessionRequest request, Principal principal, StringBuilder error) {
        ChatSessionPoJo poJo = sessionService.findById(request.getTid());
        if (poJo == null) {
            error.append(MessageFormat.format("群组(ID={0})不存在", "" + request.getTid()));
            return null;
        }

        if (!Objects.equals(poJo.getOwnerId(), currentUserId) && !sessionService.isManager(currentUserId, request.getTid())) {
            error.append("当前用户不是群主或管理员");
            return null;
        }

        ChatSessionType type = Arrays.stream(ChatSessionType.values())
                .filter(x -> x.name().equals(poJo.getType())).findFirst().orElse(null);
        assert type != null;

        JSONObject jsonObject = iYunXinInterface.kickOutSession(currentUserId, poJo.getId(), type, request.getMemberIds(), error);
        if (jsonObject == null) {
            return null;
        }

        List<OperationFailInfo> failInfos = OperationFailInfoHelper.convertTo(jsonObject);

        IExecuteResult<KickOutSessionResponse> response = sessionMemberService.kickOutSession(currentUserId, request, principal, failInfos);
        if (response.getCode() != ExecuteResult.SUCCESS_CODE) {
            error.append(response.getMsg());
            return null;
        }
        return response.getData();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean leaveSession(Long currentUserId, Long tid, Principal principal, StringBuilder error) {
        ChatSessionPoJo poJo = sessionService.findById(tid);
        if (poJo == null) {
            error.append(MessageFormat.format("群组ID(tid={0})不存在", "" + tid));
            return false;
        }
        ChatSessionType type = Arrays.stream(ChatSessionType.values())
                .filter(x -> x.name().equals(poJo.getType())).findFirst().orElse(null);
        assert type != null;

        if (!iYunXinInterface.leaveSession(currentUserId, tid, type, error)) {
            return false;
        }

        IExecuteResult<Boolean> result = sessionMemberService.leaveSession(currentUserId, tid, principal);
        if (result.getCode() != ExecuteResult.SUCCESS_CODE) {
            error.append(result.getMsg());
            return false;
        }
        return true;
    }

    @Override
    public IExecuteResult<Boolean> updateForbidRedPackage(Long currentUserId, UpdateForbidRedPackageRequest request, Principal principal, StringBuilder error) {
        return null;
    }

    @Override
    public IExecuteResult<Boolean> updateMemberNick(Long currentUserId, UpdateMemberNickRequest request, Principal principal, StringBuilder error) {
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public IExecuteResult<ChatBannedResponse> bannedMembers(Long currentUserId, ChatBannedRequest request, Principal principal, StringBuilder error) {
        ChatSessionPoJo poJo = sessionService.findById(request.getTid());
        if (poJo == null) {
            return ExecuteResult.failure(MessageFormat.format("群组ID(tid={0})不存在", "" + request.getTid()), null);
        }
        if (!Objects.equals(poJo.getOwnerId(), currentUserId)) {
            return ExecuteResult.failure("当前用户不是群主", null);
        }

        ChatSessionType type = Arrays.stream(ChatSessionType.values())
                .filter(x -> x.name().equals(poJo.getType())).findFirst().orElse(null);
        assert type != null;

        if (request.getMemberIds().size() > 10) {
            return ExecuteResult.failure("禁言人数超限(一次最多10人)", null);
        }

        JSONObject jsonObject = iYunXinInterface.bannedMembers(currentUserId, poJo.getId(), type, request, error);
        if (jsonObject == null) {
            return ExecuteResult.failure(error.toString(), null);
        }

        List<OperationFailInfo> failInfos = OperationFailInfoHelper.convertTo(jsonObject);

        IExecuteResult<ChatBannedResponse> response = sessionMemberService.bannedMembers(currentUserId, request, principal, failInfos);
        if (response.getCode() != ExecuteResult.SUCCESS_CODE) {
            return ExecuteResult.failure(response.getMsg(), null);
        }
        return ExecuteResult.success(response.getData());
    }

    @Override
    public IExecuteResult<Boolean> noDisturbingMember(Long currentUserId, NoDisturbingRequest request, Principal principal, StringBuilder error) {
        return null;
    }

    @Override
    public QueryGroupInfoResponse queryGroupList(Long currentUserId, int pageIndex, int pageSize,
                                                 Principal principal, StringBuilder error) {
        IExecuteResult<QueryGroupInfoResponse> response = sessionMemberService.queryGroupList(currentUserId, pageIndex, pageSize, principal);
        if (response.getCode() != ExecuteResult.SUCCESS_CODE) {
            error.append(response.getMsg());
            return null;
        }
        return response.getData();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        sessionService = applicationContext.getBean(ChatSessionService.class);
        sessionMemberService = applicationContext.getBean(SessionMemberService.class);
        iYunXinInterface = applicationContext.getBean(IYunXinInterface.class);
        sessionPoJoMapStruct = applicationContext.getBean(ChatSessionPoJoMapStruct.class);
        serviceProperties = applicationContext.getBean(CurrentServiceProperties.class);
    }

    private boolean sendCustomizedMessage(ChatSessionType type, ChatSessionMemberPoJo smPojo, StringBuilder error) {
        if (smPojo.getAgreeStatus() == 1) {
            //向所有有效群成员发送通知.
            Map<String, Object> push_config = new LinkedHashMap<>();
            push_config.put("push_forcepush_all", true);
            //发送群消息: 某人将某人拉人了群聊.
            IMUserPoJo userPoJo = sessionService.getCurrentUser(smPojo.getCreatorId());
            IMUserPoJo userPoJo1 = sessionService.getCurrentUser(smPojo.getMemberId());
            String content = MessageFormat.format("{0}邀请{1}加入了群聊", userPoJo.getNickname(), userPoJo1.getNickname());
            return iYunXinInterface.sendCustomizedMessage(smPojo.getCreatorId(),
                    type.getType() + 1, smPojo.getSessionId(), content, null, null, push_config, error);
        }
        return false;
    }

    private List<ChatSessionDetailVo> convertTo(List<ChatSessionPoJo> sessionPoJos) {
        List<ChatSessionDetailVo> voList = sessionPoJoMapStruct.toChatSessionDetailVos(sessionPoJos);
        for (ChatSessionDetailVo vo : voList) {
            //群组头像。
            String avatarUrl = "http://" + serviceProperties.getExternalManagerService() + vo.getAvatar();
            vo.setAvatar(avatarUrl);
        }
        return voList;
    }

}
